package com.win.oauth.controller;


import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.fyl.controller.BaseController;
import com.fyl.core.response.RS;
import com.fyl.utils.BaseTreeUtil;
import com.win.oauth.constant.OAuthConst;
import com.win.oauth.dto.AntdSelectTreeDTO;
import com.win.oauth.dto.FunPermissionDTO;
import com.win.oauth.dto.ModulePermissionDTO;
import com.win.oauth.dto.ModuleTreeDTO;
import com.win.oauth.entity.Fun;
import com.win.oauth.entity.Module;
import com.win.oauth.entity.Permission;
import com.win.oauth.entity.RolePermissionRel;
import com.win.oauth.service.IFunService;
import com.win.oauth.service.IModuleService;
import com.win.oauth.service.IPermissionService;
import com.win.oauth.service.IRolePermissionRelService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * <p>
 * 前端控制器
 * </p>
 *
 * @author youlian.fei
 * @since 2020-03-14
 */
@RestController
@RequestMapping("/oauth/module")
public class ModuleController extends BaseController<IModuleService, Module> {

    @Autowired
    IFunService funService;

    @Autowired
    IPermissionService permissionService;

    @Autowired
    IRolePermissionRelService rolePermissionRelService;

    @GetMapping("/getTree")
    public RS<List<ModuleTreeDTO>> getTree() {
        List<ModulePermissionDTO> list = baseService.selectListDTO();
        List<ModuleTreeDTO> resp = BaseTreeUtil.build(el -> {
            ModuleTreeDTO dto = new ModuleTreeDTO();
            BeanUtils.copyProperties(el, dto);
            return dto;
        }, list);
        return RS.genSuccess(resp);
    }

    @GetMapping("/getParentSelect")
    public RS<List<AntdSelectTreeDTO>> getParentSelect(@RequestParam(required = false) Long selfId) {

        LambdaQueryWrapper<Module> qw = new LambdaQueryWrapper<Module>()
                .ne(null != selfId, Module::getId, selfId)
                .notLike(null != selfId, Module::getNode, OAuthConst.TREE_NODE_PREFIX + selfId + OAuthConst.TREE_NODE_DELIMITER);

        List<Module> list = baseService.list(qw);
        List<AntdSelectTreeDTO> resp = BaseTreeUtil.build(el -> {
            AntdSelectTreeDTO dto = new AntdSelectTreeDTO();
            dto.setId(el.getId());
            dto.setParentId(el.getParentId());
            dto.setKey(el.getId());
            dto.setValue(el.getId());
            dto.setLabel(el.getName());
            return dto;
        }, list);
        return RS.genSuccess(resp);
    }


    @PostMapping("/saveCascade")
    public RS<ModulePermissionDTO> saveCascade(@RequestBody ModulePermissionDTO dto) {
        Module module = new Module();
        dto.buildModel(module);

        Permission permission = new Permission();
        permission.setId(dto.getPermId());
        permission.setType(OAuthConst.PERMISSION_TYPE_MODULE);
        permission.setUrl(dto.getUrl());

        baseService.saveCascade(module, permission);

        dto.setId(module.getId());
        dto.setPermId(permission.getId());
        return RS.genSuccess(dto);
    }

    @GetMapping("/getFuns")
    public RS<List<FunPermissionDTO>> getFuns(@RequestParam Long id) {
        List<FunPermissionDTO> list = funService.selectByModule(id);
        return RS.genSuccess(list);
    }

    @Override
    public RS<Module> get(@RequestParam Long id) {
        ModulePermissionDTO dto = baseService.getById(id);
        return RS.genSuccess(dto);
    }

    @PostMapping("/delCascade")
    public RS<Void> delCascade(@RequestBody Module moduleReq) {
        ModulePermissionDTO module = baseService.getById(moduleReq.getId());
        // role module 绑定 判断
        List<Module> modules = baseService.lambdaQuery().likeRight(Module::getNode, module.getNode()).list();
        if (!modules.isEmpty()) {
            List<Long> moduleIds = modules.stream().map(Module::getId).collect(Collectors.toList());
            List<Permission> permissions = permissionService.lambdaQuery()
                    .eq(Permission::getType, OAuthConst.PERMISSION_TYPE_MODULE)
                    .in(Permission::getModuleFunId, moduleIds)
                    .list();
            if (!permissions.isEmpty()) {
                List<Long> permissionIds = permissions.stream().map(Permission::getId).collect(Collectors.toList());
                Integer count = rolePermissionRelService.lambdaQuery().in(RolePermissionRel::getPermissionId, permissionIds).count();
                if (count > 0) {
                    return RS.genFail("该菜单或其下级被角色绑定中,无法删除!");
                }
            }
        }
        // role 绑定 判断
        List<Fun> funs = funService.lambdaQuery().likeRight(Fun::getNode, module.getNode()).list();
        if (!funs.isEmpty()) {
            List<Long> funIds = funs.stream().map(Fun::getId).collect(Collectors.toList());
            List<Permission> permissions = permissionService.lambdaQuery()
                    .eq(Permission::getType, OAuthConst.PERMISSION_TYPE_FUN)
                    .in(Permission::getModuleFunId, funIds)
                    .list();
            if (!permissions.isEmpty()) {
                List<Long> permissionIds = permissions.stream().map(Permission::getId).collect(Collectors.toList());
                Integer count = rolePermissionRelService.lambdaQuery().in(RolePermissionRel::getPermissionId, permissionIds).count();
                if (count > 0) {
                    return RS.genFail("该菜单或其下级被角色绑定中,无法删除!");
                }
            }
        }
        // 级联删除 菜单 及其子级
        baseService.delCascade(module);
        return RS.genSuccess();
    }


}
